{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Eigenmode and EPR analysis\n",
    "### Prerequisite\n",
    "You need to have a working local installation of Ansys."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Sections\n",
    "### I. Transmon only\n",
    "1. Prepare the layout in qiskit-metal. <br>\n",
    "1. Run finite element eigenmode analysis. <br>\n",
    "1. Plot fields and display them. <br>\n",
    "1. Set up EPR junction dictionary. <br>\n",
    "1. Run EPR analysis on single mode. <br>\n",
    "1. Get qubit freq and anharmonicity. <br>\n",
    "1. Calculate EPR of substrate.  <br>\n",
    "1. (Extra: Calculate surface EPR.) <br>\n",
    "\n",
    "### II. Resonator only\n",
    "1. Update the layout in qiskit-metal. <br>\n",
    "1. Run finite element eigenmode analysis. <br>\n",
    "1. Plot fields and display them. <br>\n",
    "1. Calculate EPR of substrate. <br>\n",
    "    \n",
    "### III. Transmon & resonator\n",
    "1. Update the layout in qiskit-metal. <br>\n",
    "1. Run finite element eigenmode analysis. <br>\n",
    "1. Plot fields and display them. <br>\n",
    "1. Set up EPR junction dictionary. <br>\n",
    "1. Run EPR analysis on the two modes. <br>\n",
    "1. Get qubit frequency and anharmonicity. <br>\n",
    "\n",
    "### IV. Analyze a coupled 2 transmon system. \n",
    "1. Finite Element Eigenmode Analysis\n",
    "1. Identify the mode you want. The mode can inclusively be from 1 to setup.n_modes.\n",
    "1. Set variables in the Ansys design. As before, we seek 2 modes.\n",
    "1. Set up the simulation and specify the variables for the sweep.\n",
    "1. Plot the E-field on the chip's surface.\n",
    "1. Specify the junctions in the model; in this case there are 2 junctions.\n",
    "1. Find the electric and magnetic energy stored in the substrate and the system as a whole.\n",
    "1. Perform EPR analysis for all modes and variations."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%reload_ext autoreload\n",
    "%autoreload 2\n",
    "\n",
    "import qiskit_metal as metal\n",
    "from qiskit_metal import designs, draw\n",
    "from qiskit_metal import MetalGUI, Dict, Headings\n",
    "import pyEPR as epr"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 1. Analyze the transmon qubit by itself\n",
    "\n",
    "We will use the analysis package - applicable to most users. Advanced users might want to expand the package, or directly interact with the renderer. The renderer is one of the properties of the analysis class.\n",
    "\n",
    "### Create the Qbit design\n",
    "\n",
    "Setup a design of a given dimension. Dimensions will be respected in the design rendering. <br>\n",
    "Note that the design size extends from the origin into the first quadrant."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "design = designs.DesignPlanar({}, True)\n",
    "design.chips.main.size['size_x'] = '2mm'\n",
    "design.chips.main.size['size_y'] = '2mm'\n",
    "\n",
    "gui = MetalGUI(design)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Create a single transmon with one readout resonator and move it to the center of the chip previously defined."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "from qiskit_metal.qlibrary.qubits.transmon_pocket import TransmonPocket\n",
    "\n",
    "design.delete_all_components()\n",
    "\n",
    "q1 = TransmonPocket(design, 'Q1', options = dict(\n",
    "    pad_width = '425 um', \n",
    "    pocket_height = '650um',\n",
    "    connection_pads=dict(\n",
    "        readout = dict(loc_W=+1,loc_H=+1, pad_width='200um')\n",
    "    )))\n",
    "\n",
    "gui.rebuild()\n",
    "gui.autoscale()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Finite Element Eigenmode Analysis\n",
    "\n",
    "#### Setup\n",
    "\n",
    "Select the analysis you intend to run from the `qiskit_metal.analyses` collection.<br>\n",
    "Select the design to analyze and the tool to use for any external simulation."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from qiskit_metal.analyses.quantization import EPRanalysis"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "eig_qb = EPRanalysis(design, \"hfss\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Review and update the convergence parameters and junction properties by executing following two cells. We exemplify three different methods to update the setup parameters."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "eig_qb.sim.setup"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# example: update single setting\n",
    "eig_qb.sim.setup.max_passes = 6\n",
    "eig_qb.sim.setup.vars.Lj = '11 nH'\n",
    "# example: update multiple settings\n",
    "eig_qb.sim.setup_update(max_delta_f = 0.4, min_freq_ghz = 1.1)\n",
    "\n",
    "eig_qb.sim.setup"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Execute simulation and verify convergence and EM field\n",
    "Analyze a single qubit with shorted terminations. Then observe the frequency convergence plot. If not converging, you might want to increase the min_passes value to force the renderer to increase accuracy.\n",
    "\n",
    "You can use the method `run()` instead of `sim.run()` in the following cell if you want to run both eigenmode and epr analysis in a single step. If so, make sure to also tweak the setup for the epr analysis. The input parameters are otherwise the same for the two methods."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "eig_qb.sim.run(name=\"Qbit\", components=['Q1'], open_terminations=[], box_plus_buffer = False)\n",
    "eig_qb.sim.plot_convergences()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The last variables you pass to the `run()` or `sim.run()` methods, will be stored in the `sim.setup` dictionary under the key `run`. You can recall the information passed by either accessing the dictionary directly, or by using the print handle below."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# eig_qb.setup.run    <- direct access\n",
    "eig_qb.sim.print_run_args()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "(optional) Captures the renderer GUI"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "eig_qb.sim.save_screenshot()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "(optional) Work directly with the convergence numbers"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "eig_qb.sim.convergence_f"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "(optional) You can re-run the analysis after varying the parameters.<br>\n",
    "Not passing the parameter `components` to the `sim.run()` method, skips the rendering and tries to run the analysis on the latest design. If a design is not found, the full metal design is rendered."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "eig_qb.sim.setup.min_freq_ghz = 4\n",
    "eig_qb.sim.run()\n",
    "eig_qb.sim.convergence_f"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Verify that the Electro(magnetic) fields look realistic."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "eig_qb.sim.plot_fields('main')   # TODO:::: Ez, normal component.....decide which field typically on the qbit, or on the crossing between meanders\n",
    "eig_qb.sim.save_screenshot()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "(optional) clear the renderer by removing the fields"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "eig_qb.sim.clear_fields()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### EPR Analysis\n",
    "#### Setup\n",
    "Identify the non-linear (Josephson) junctions in the model. You will need to list the junctions in the epr setup.\n",
    "\n",
    "In this case there's only one junction, namely 'jj'. Let's see what we need to change in the default setup."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "eig_qb.setup"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The name of the `Lj_variable` and `Cj_variable` match with our model. However it is missing the names of the shapes that identify the junction (`rect` and `line`). Look for those in the renderer and find the name. Then let's change the name (See below)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "eig_qb.setup.junctions.jj.rect = 'JJ_rect_Lj_Q1_rect_jj'\n",
    "eig_qb.setup.junctions.jj.line = 'JJ_Lj_Q1_rect_jj_'\n",
    "eig_qb.setup"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We will now run epr as a single step. On screen you will observe various information in this order:\n",
    "* stored energy = Electric and magnetic energy stored in the substrate and the system as a whole.\n",
    "* EPR analysis results for all modes/variations.\n",
    "* Spectrum analysis.\n",
    "* Hamiltonian report."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "eig_qb.run_epr()\n",
    "\n",
    "#### equivalent individual calls\n",
    "# s = self.setup\n",
    "# self.epr_start()\n",
    "# eig_qb.get_stored_energy()\n",
    "# eig_qb.run_analysis()\n",
    "# eig_qb.spectrum_analysis(s.cos_trunc, s.fock_trunc)\n",
    "# eig_qb.report_hamiltonian(s.swp_variable)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 2. Analyze the CPW resonator by itself\n",
    "### Update the design in Metal\n",
    "Connect the transmon to a CPW. <br>\n",
    "The other end of the CPW connects to an open to ground termination."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from qiskit_metal.qlibrary.terminations.open_to_ground import OpenToGround\n",
    "from qiskit_metal.qlibrary.tlines.meandered import RouteMeander\n",
    "otg = OpenToGround(design, 'open_to_ground', options=dict(pos_x='1.75mm',  pos_y='0um', orientation='0'))\n",
    "RouteMeander(design, 'readout',  Dict(\n",
    "        total_length='6 mm',\n",
    "        hfss_wire_bonds = True,\n",
    "        fillet='90 um',\n",
    "        lead = dict(start_straight='100um'),\n",
    "        pin_inputs=Dict(\n",
    "            start_pin=Dict(component='Q1', pin='readout'),\n",
    "            end_pin=Dict(component='open_to_ground', pin='open')), ))\n",
    "\n",
    "gui.rebuild()\n",
    "gui.autoscale()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Finite Element Eigenmode Analysis\n",
    "\n",
    "#### Setup\n",
    "\n",
    "Create a separate analysis object, dedicated to the readout. This allows to retain the Qubit session active, in case we will later need to tweak the design and repeat the simulation. When different renderers are available you could even consider using different more appopriate ones for each simulation steps of this notebook, but for now we will be using the same one."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "eig_rd = EPRanalysis(design, \"hfss\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "For the resonator analysis we will use the default setup. Youn can feel free to edit it the same way we did in section 1.\n",
    "\n",
    "#### Execute simulation and verify convergence and EM field\n",
    "Analyze the readout in isolation. Select the readout and terminate it with an open on both ends. Note that we are selecting for this analysis both the `readout` component and the `open_to_ground` component. The `open_to_ground` compoent might feel redundant because we are specifying in that open in the `open_terminations`, and the end converging reult is indeed the same. however the `open_to_ground` appears to help the system to ceonverge faster, so we keep it in there."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "eig_rd.sim.run(name=\"Readout\",\n",
    "               components=['readout', 'open_to_ground'],\n",
    "               open_terminations=[('readout', 'start'), ('readout', 'end')])\n",
    "eig_rd.sim.plot_convergences()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "eig_rd.sim.save_screenshot()  # optional"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Recover eigenmode frequencies for each variation."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "eig_rd.get_frequencies()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Display the Ansys modeler window and plot the E-field on the chip's surface."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "eig_rd.sim.plot_fields('main')\n",
    "eig_rd.sim.save_screenshot()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Refine\n",
    "\n",
    "If convergence is not complete, or the EM field is unclear, update the number of passes and re-run the flow (below repeated for convenience)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "eig_rd.sim.setup.max_passes = 15   # update single setting\n",
    "eig_rd.sim.run()\n",
    "eig_rd.sim.plot_convergences()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Display the Ansys modeler window again and plot the E-field on the chip's surface with this updated number of passes. <br>\n",
    "Note that the bright areas have become much smoother compared to the previous image, indicating better convergence."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "eig_rd.sim.plot_fields('main')\n",
    "eig_rd.sim.save_screenshot()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### EPR Analysis\n",
    "Find the electric and magnetic energy stored in the readout system."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "eig_rd.run_epr(no_junctions = True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 3. Analyze the combined transmon + CPW resonator system\n",
    "\n",
    "### Finite Element Eigenmode Analysis\n",
    "\n",
    "#### Setup\n",
    "\n",
    "Create a separate analysis object for the combined qbit+readout."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "eig_qres = EPRanalysis(design, \"hfss\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "For the resonator analysis we look for 2 eigenmodes - one with stronger fields near the transmon, the other with stronger fields near the resonator. Therefore let's update the setup accordingly."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "eig_qres.sim.setup.n_modes = 2\n",
    "eig_qres.sim.setup"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Execute simulation and verify convergence and EM field\n",
    "Analyze the qubit+readout. Select the qubit and the readout, then finalize with open termination on the other pins."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "eig_qres.sim.run(name=\"TransmonResonator\",\n",
    "                 components=['Q1', 'readout', 'open_to_ground'],\n",
    "                 open_terminations=[('readout', 'end')])\n",
    "eig_qres.sim.plot_convergences()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "eig_qres.sim.save_screenshot()  # optional"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Display the Ansys modeler window again and plot the E-field on the chip's surface. you can select which of the two modes to visualize."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "eig_qres.sim.plot_fields('main', eigenmode=1)\n",
    "eig_qres.sim.save_screenshot()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### EPR Analysis"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Similarly to section 1, we need to pass to the renderer the names of the shapes that identify the junction (`rect` and `line`). These should be the same as in section 1, or you can look again for those in the renderer."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "eig_qres.setup.junctions.jj.rect = 'JJ_rect_Lj_Q1_rect_jj'\n",
    "eig_qres.setup.junctions.jj.line = 'JJ_Lj_Q1_rect_jj_'\n",
    "eig_qres.setup"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We will now run epr as a single step. On screen you will observe various information in this order:\n",
    "* stored energy = Electric and magnetic energy stored in the substrate and the system as a whole.\n",
    "* EPR analysis results for all modes/variations.\n",
    "* Spectrum analysis.\n",
    "* Hamiltonian report."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "eig_qres.run_epr()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Once you are sure you are done with the qubit analysis, please explicitly release the Ansys session to allow for a smooth close of the external tool."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "eig_qb.sim.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "eig_rd.sim.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "eig_qres.sim.close()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 4. Analyze a coupled 2-transmon system\n",
    "### Create the design\n",
    "\n",
    "This is a different system than the one analyzed in sections 1,2,3. Therefore, let's start by deleting the design currntly in the Qiskit Metal GUI (if any)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "design.delete_all_components()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next, we create the `TwoTransmon` design, consisting of 2 transmons connected by a short coupler."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from qiskit_metal.qlibrary.qubits.transmon_pocket import TransmonPocket\n",
    "from qiskit_metal.qlibrary.tlines.straight_path import RouteStraight\n",
    "\n",
    "q1 = TransmonPocket(design, 'Q1', options = dict(\n",
    "    pad_width = '425 um', \n",
    "    pocket_height = '650um',\n",
    "    connection_pads=dict(\n",
    "        readout = dict(loc_W=+1,loc_H=+1, pad_width='200um')\n",
    "    )))\n",
    "\n",
    "q2 = TransmonPocket(design, 'Q2', options = dict(\n",
    "    pos_x = '1.0 mm',\n",
    "    pad_width = '425 um', \n",
    "    pocket_height = '650um',\n",
    "    connection_pads=dict(\n",
    "        readout = dict(loc_W=-1,loc_H=+1, pad_width='200um')\n",
    "    )))\n",
    "\n",
    "coupler = RouteStraight(design, 'coupler', Dict(hfss_wire_bonds = True,\n",
    "        pin_inputs=Dict(\n",
    "            start_pin=Dict(component='Q1', pin='readout'),\n",
    "            end_pin=Dict(component='Q2', pin='readout')), ))\n",
    "\n",
    "gui.rebuild()\n",
    "gui.autoscale()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's observe the current table describing the junctions in the qiskit metal design"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "design.qgeometry.tables['junction']"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can observe in the table above that every junction has been assigned a default inductance, capacitance and resistance values, based on the originating component class `default_options`. In this example we intend to replace those values with a variable name, which will later be set directly in the renderer. Therefore, let's proceed with updating these values in the qubit instances, and then propagate the update to the table with a `rebuild()`.\n",
    "After executing the cell below, you can observe the change by re-executing the cell above."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# TODO: fold this inside either an analysis class method, or inside the analysis class setup\n",
    "\n",
    "qcomps = design.components  # short handle (alias)\n",
    "qcomps['Q1'].options['hfss_inductance'] = 'Lj1'\n",
    "qcomps['Q1'].options['hfss_capacitance'] = 'Cj1'\n",
    "qcomps['Q2'].options['hfss_inductance'] = 'Lj2'\n",
    "qcomps['Q2'].options['hfss_capacitance'] = 'Cj2'\n",
    "gui.rebuild()  # line needed to propagate the updates from the qubit instance into the junction design table\n",
    "gui.autoscale()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Finite Element Eigenmode Analysis\n",
    "\n",
    "#### Setup\n",
    "\n",
    "Let's start the analysis by creating the appropriate analysis object."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from qiskit_metal.analyses.quantization import EPRanalysis\n",
    "eig_2qb = EPRanalysis(design, \"hfss\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now let us update the setup of this analysis to reflect what we plan to do:\n",
    "* define the variables that we have assigned to the inductance and capacitance of the junctions;\n",
    "* increase accuracy of the convergence;\n",
    "* observe the eigenmode corresponding to both qubits."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "eig_2qb.sim.setup.max_passes = 15\n",
    "eig_2qb.sim.setup.max_delta_f = 0.05\n",
    "eig_2qb.sim.setup.n_modes = 2\n",
    "eig_2qb.sim.setup.vars = Dict(Lj1= '13 nH', Cj1= '0 fF',\n",
    "                           Lj2= '9 nH', Cj2= '0 fF')\n",
    "eig_2qb.sim.setup"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "By default, the analysis will be done on all components that we will list in the `run_sim()` method, but the analysis needs to know how much of the ground plane around the qubit to consider. One could use the declared chip dimension by passing the parameter `bux_plus_buffer = False` to the `run_sim()` method. However, its default (when said parameter is omitted) is to consider the ground plane to be as big as the minimum enclosing rectangle plus a set buffer. The default buffer value is `200um`, while in the cell below we will increase as an example that buffer to `500um`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# TODO: fold this inside either an analysis class method, or inside the analysis class setup\n",
    "\n",
    "eig_2qb.sim.renderer.options['x_buffer_width_mm'] = 0.5\n",
    "eig_2qb.sim.renderer.options['y_buffer_width_mm'] = 0.5\n",
    "eig_2qb.sim.renderer.options"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's finally run the cap extraction simulation and observe the convergence."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "eig_2qb.sim.run(name=\"TwoTransmons\",\n",
    "                components=['coupler', 'Q1', 'Q2'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "eig_2qb.sim.plot_convergences()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "eig_2qb.sim.save_screenshot()  # optional"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Display the Ansys modeler window again and plot the E-field on the chip's surface. Since we have analyzed 2 modes, you will need to select which mode to visualize. The default is mode 1, but the mode can inclusively be any integer between 1 and `setup.n_modes`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "eig_2qb.sim.plot_fields('main', eigenmode=2)\n",
    "eig_2qb.sim.save_screenshot()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### EPR Analysis\n",
    "#### Setup\n",
    "Identify the non-linear (Josephson) junctions in the model. in this case there are 2 junctions, which we will refer to as `jj1` and `jj2`. Also define the dissipative reference shapes. Remove the default junction and create the two."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "del eig_2qb.setup.junctions['jj']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "eig_2qb.setup.junctions.jj1 = Dict(rect='JJ_rect_Lj_Q1_rect_jj', line='JJ_Lj_Q1_rect_jj_',\n",
    "                  Lj_variable='Lj1', Cj_variable='Cj1')\n",
    "eig_2qb.setup.junctions.jj2 = Dict(rect='JJ_rect_Lj_Q2_rect_jj', line='JJ_Lj_Q2_rect_jj_',\n",
    "                  Lj_variable='Lj2', Cj_variable='Cj2')\n",
    "eig_2qb.setup.sweep_variable = 'Lj1'\n",
    "eig_2qb.setup"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Find the electric and magnetic energy stored in the substrate and the system as a whole."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "eig_2qb.run_epr()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Release Ansys's session"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "eig_2qb.sim.close()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "(optional) **final wrap**: Close the gui by removing the # in the line below."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# gui.main_window.close()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
